-
参数
形参(parameter):函数中定义的变量
实参(argument):运行时的函数调用时传入的参数
上下文(context):通过对象来调用函数时,这个对象就是this就是上下文;
闭包(closure):函数嵌套在函数当中
1 函数调用的方式
有4种方法来调用JavaScript函数:
作为函数
作为方法
作为构造函数
通过call方法和apply方法间接调用
ES3 和非严格模式下的ES5中,调用上下文(this的值)是全局对象。在严格模式下,调用上下文则是undefined
1.1 函数调用
语法:
functionName()
window.name = "hello";
(function () {
console.log(this); //window
})()
"use strict";
window.name = "hello";
(function () {
console.log(this); //undefined
})()
1.2 方法调用
语法:
obj.functionName()
方法和this关键字是面向对象编程规范的核心
方法链
方法链:当方法的返回值是一个对象,这个对象还可以再调用它的方法。这个方法调用序列就是方法链;
1.3 构造函数调用
没有形参的构造函数调用都可以省略小括号
1.4 间接调用
call方法:使用它自有的实参列表作为函数的实参;
apply方法:要求以数组的形式传入参数;
2 函数的实参和形参
2.1 可选形参
当调用函数的时候传入的实参比函数声明时指定的形参个数要少,剩下的形参都将是undefined;所以在定义函数的时候应当给省略的参数赋一个默认值:
function pushArray(o, /* optional */ a) {
if (a === undefined) a = [];
// a = a || [];
for (var property in o) a.push(property);
return a;
}
var o = {
name: "Oliver",
age: 18
};
var a = ["friends"];
console.log(pushArray(o, a).toString()); //friends,name,age
2.2 实参对象
省略的实参都是undefined;多出的参数自动忽略
另外,可以通过arguments来获取多余的参数,arguments.length获得参数个数
不定实参函数(varargs function):接收任意个数的实参
不定实参函数的实参个数不能为零;
ES5之前,arguments[0]和x指代同一个值;
function pushArray(a) {
console.log(a); //Array
arguments[0] = 10;
console.log(a); //Array
console.log(arguments[0]); //10
}
var a = ["friends"];
pushArray(a);
2.3 将对象属性用作实参
最好通过名值对的形式传入参数(传入的实参都写入一个单独的对象之中,在调用的时候传入一个对象)
function outputString(obj) {
var fname = obj.firstName,
lname = obj.lastName,
age = obj.age;
console.log(`your fisrtName: ${fname}; lastName: ${lname}; age: ${age}`);
}
outputString({firstName: "Oliver", lastName: "Young", age: 18}); //your fisrtName: Oliver; lastName: Young;
3 作为值的函数
函数也是值,可以将函数赋值给变量,存储在对象的属性和数组的元素中,作为参数传入另外一个函数等
函数是对象,可以定义自己的属性
log.conter = 10;
function log () {
console.log(log.conter);
}
log(); //10
这样函数就不需要再定义一个全局变量
4作为命名空间的函数
将代码放入一个函数内,然后调用这个函数:
不同的写法:
function log (i) {
console.log("hello" +i);
}
log(100);
(function log (i) {
console.log("hello" + i);
}(100))
(function log (i) {
console.log("hello" + i);
})(100)
小括号括起来避免JavaScript解释器解析为函数声明语句
5 闭包
词法作用域(lexical scoping):函数的执行依赖于变量作用域,这个作用域是在函数定义时决定的,而不是函数调用时决定的。
闭包:函数对象可以通过作用域相互关联起来,函数体内部的变量都可以保存在函数作用域内。
上面的log.conter属性就可以使用包括在闭包中:
var pro = (function() {
var conter = 10;
function log(argument) {
console.log(conter++);
}
return log;
})();
pro(); //10
pro(); //11
pro(); //12
使用多个嵌套函数:
function counter () {
var num = 0;
return {
count: function () {
return num ++;
},
reset: function () {
num = 0;
}
};
}
var newCounter = counter(); //这里是新的计数器,再赋值一个变量可以得到另外一个计数器,两者不受影响
console.log(newCounter.count()); //0
console.log(newCounter.count()); //1
console.log(newCounter.count()); //2
newCounter.reset();
console.log(newCounter.count()); //0
console.log(newCounter.count()); //1
console.log(newCounter.count()); //2
6 函数属性、方法和构造函数
6.1 length属性
函数的length返回的是形参的数量;函数内部arguments.length返回的是实参的数量
function add(x, y) {
return arguments.length;
}
console.log(add.length); //2
console.log(add(1)); //1
6.2 prototype属性
6.3 call()和apply()方法
通过调用方法的形式来间接调用函数,call和apply的第一个实参是要调用函数的母对象,它是调用上下文。
比如,以对象o的方法的形式调用函数f()并传入两个参数:f.call(o, 1, 2)
apply可以传入的参数可以是数组和类数组的。
6.4 bind()方法
ES5的该方法主要作用是将函数绑定至某个对象,方法返回一个新的函数,调用这个新的函数会把绑定的函数在对象中当做方法来调用。
function add(y) {
return this.x + y;
}
var o = {
x: 100
};
var g = add.bind(o);
console.log(g(100)); //200
柯里化(currying):除了第一个实参外,传入bind的实参也会绑定至this;
function add(x, y) {
return x + y;
}
var o = {
};
var g = add.bind(o, 100); //x是100
console.log(g(100)); //200 y是100
//上面的o对象可以去掉:
function add(x, y, z) {
return x + y + z;
}
var g = add.bind(null, 100, 100, 100); //x是100 y是100 z是100
console.log(g()); //300
//又如:
function add(y, z) {
return this.x + y + z;
}
var g = add.bind({x:100}, 100, 100); //{x是100} y是100 z是100
console.log(g()); //300
6.5 toString()方法
6.6 Function()构造函数
Function()构造函数所创建的函数并不是使用此法作用域:
var scope = "global";
function constructFunction () {
var scope = "local";
return new Function("return scope");
}
console.log(constructFunction()()); //global
var scope = "global";
function constructFunction () {
var scope = "local";
return function () {
return scope
};
}
console.log(constructFunction()()); //local
6.7 可调用的对象
7 函数式编程
7.1 使用函数处理数组
如要计算元素的平均值:
var arr = [1,2,3,4,5];
var total = 0;
for (var i = 0; i < arr.length; i++) {
total += arr[i];
};
var result = total/arr.length;
console.log(result); //3
函数式编程风格:
var arr = [1,2,3,4,5];
function sum (a, b) {
return a + b;
}
var total = arr.reduce(sum);
var result = total/arr.length;
console.log(result); //3
7.2 高阶函数
高阶函数(higher-order function):就是操作函数的函数,它接收一个或多个函数作为参数,并返回一个新函数
function reverse(fun) {
return function () {
var result = fun.apply(this, arguments);
return !result;
}
}
var even = function (x) {
return x % 2 === 0;
};
var odd = reverse(even);
console.log(odd(100)); //False
console.log(even(100)); //True
7.3 不完全函数
7.4 记忆
记忆(memorization):部分结果在函数式编程中被缓存起来,这种缓存技巧就是“记忆”
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。